package com.aq.appserver.server.account.service.impl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.aq.appserver.common.util.PWDUtil;
import com.aq.appserver.server.account.bean.AccountBean;
import com.aq.appserver.server.account.bean.AccountBeanPad;
import com.aq.appserver.server.account.bean.AccountBeanWeb;
import com.aq.appserver.server.account.dao.AccountDao;
import com.aq.appserver.server.account.dao.FeatherDao;
import com.aq.appserver.server.account.dao.HeadImgDao;
import com.aq.appserver.server.account.entity.Account;
import com.aq.appserver.server.account.entity.Feather;
import com.aq.appserver.server.account.entity.HeadImg;
import com.aq.appserver.server.account.service.AccountService;

@Service
public class AccountServiceImpl implements AccountService{

	@Autowired
	private AccountDao accountDao;
	
	@Autowired
	private HeadImgDao headImgDao;
	
	@Autowired
	private FeatherDao featherDao;

	private List<AccountBean> list;
	
	private static int getRandom(int count) 
	{
		return (int) Math.round(Math.random() * (count));
	}
	
	private static String string = "1234567890abcdefghijklmnopqrstuvwxyz";
	
	private static String getRandomString(int length){
	    StringBuffer sb = new StringBuffer();
	    int len = string.length();
	    for (int i = 0; i < length; i++) {
	        sb.append(string.charAt(getRandom(len-1)));
	    }
	    return sb.toString();
	}
	
	@Override
	@Transactional(propagation=Propagation.REQUIRED)
	public void save(Account account) {
		account.setRegisterCode(getRandomString(8));
		accountDao.save(account);
		String refCode = account.getRefCode();
		if (!StringUtils.isEmpty(refCode)) {
			Account act = accountDao.findByRegisterCode(refCode);
			if (act != null)  {
				accountDao.updateAccFeather(act.getPhoneNumber(), 50);
			}
		}
	}

	@Override
	public Account findByPhoneNumber(String phoneNumber) {
		return accountDao.findByPhoneNumber(phoneNumber);
	}

	@Override
	public AccountBeanPad findByPhoneNumberAndPassword(AccountBean accountBean) {
		return accountDao.findByPhoneNumberAndPassword(accountBean.getLoginName(), accountBean.getPassword());
	}

	@Override
	public void saveHeadImg(HeadImg headImg) {
		headImgDao.save(headImg);
	}

	@Override
	@Transactional
	public void updateHeadImg(HeadImg headImg) {
		headImgDao.updateHeadImg(headImg.getUrl(), headImg.getPhoneNumber(), headImg.getType());
	}

	@Override
	public AccountBeanPad findByQqUuid(String uuid) {
		return accountDao.findByQqUuid(uuid);
	}

	@Override
	public AccountBeanPad findByWxUuid(String uuid) {
		return accountDao.findByWxUuid(uuid);
	}

	@Override
	public AccountBeanPad findByWbUuid(String uuid) {
		return accountDao.findByWbUuid(uuid);
	}

	@Override
	@Transactional
	public void updateQqUuidByLoginName(String loginName, String uuid) {
		accountDao.updateQqUuidByLoginName(loginName, uuid);
	}

	@Override
	@Transactional
	public void updateWxUuidByLoginName(String loginName, String uuid) {
		accountDao.updateWxUuidByLoginName(loginName, uuid);
	}

	@Override
	@Transactional
	public void updateWbUuidByLoginName(String loginName, String uuid) {
		accountDao.updateWbUuidByLoginName(loginName, uuid);
	}

	@Override
	public Page<AccountBeanWeb> queryAccountList(String accCondition,
			Pageable pageable) {
		return null;
	}

	@Override
	@Transactional
	public void updateSpeakState(AccountBean accountBean) {
		accountDao.updateSpeakState(accountBean.getPhoneNum(), accountBean.getStatus());
	}

	@Override
	public Feather findByPhoneNum(String mobile) {
		return featherDao.findByPhoneNum(mobile);
	}

	@Override
	public void saveFeather(Feather featherInfo) {
		featherDao.save(featherInfo);
	}

	@Override
	@Transactional
	public void updateAccFeather(String phoneNum, int count) {
		accountDao.updateAccFeather(phoneNum, count);
	}

	@Override
	@Transactional
	public void updateFeather(String phoneNum, int count, Date date) {
		featherDao.updateFeather(phoneNum, count, date);
	}

	@Override
	@Transactional
	public void updateNickName(AccountBeanPad accountBeanPad) {
		accountDao.updateNickName(accountBeanPad.getPhoneNumber(), accountBeanPad.getNickName());
	}

	@Override
	public List<AccountBean> queryAccountListWeb(AccountBean bean, Pageable pageable) {
		final String nickName = bean.getNickName();
		final String phoneNumber = bean.getPhoneNum();
		Iterator<Account> it;
		if(StringUtils.isEmpty(nickName)&&StringUtils.isEmpty(phoneNumber))
		{
			Iterable<Account> itb = accountDao.findAll(pageable);
			it = itb.iterator();
		}
		else
		{
			//it = accountDao.findByNickNameLikeOrPhoneNumberLike(nickName, phoneNumber, pageable).iterator();
			Specification<Account> spec = new Specification<Account>() { 
				public Predicate toPredicate(Root<Account> root,  
				        CriteriaQuery<?> query, CriteriaBuilder cb) {  
				    List<Predicate> list = new ArrayList<Predicate>();  
				    if(!StringUtils.isEmpty(nickName) && !StringUtils.isEmpty(phoneNumber)){  
				        list.add(cb.like(root.get("nickName").as(String.class), "%"+ nickName +"%"));  
				        list.add(cb.like(root.get("phoneNumber").as(String.class), "%"+ phoneNumber +"%"));  
				    } else if (!StringUtils.isEmpty(nickName)) {
				        list.add(cb.like(root.get("nickName").as(String.class), "%"+ nickName +"%"));  
				    } else if (!StringUtils.isEmpty(phoneNumber)) {
				        list.add(cb.like(root.get("phoneNumber").as(String.class), "%"+ phoneNumber +"%"));  
				    }
				    Predicate[] p = new Predicate[list.size()];  
				    return cb.and(list.toArray(p));  
				}
			};
			it = accountDao.findAll(spec, pageable).iterator();
		}
		 
		List<AccountBean> list = new ArrayList<AccountBean>();
		while(it.hasNext())
		{
			Account one = it.next();
			AccountBean ab = new AccountBean();
			ab.setAccountID(one.getId() + "");
			ab.setNickName(one.getNickName());
			ab.setPhoneNum(one.getPhoneNumber());
			ab.setFeatherNum(one.getFeather());
			ab.setQq(one.getQqUuid());
			ab.setWx(one.getWxUuid());
			ab.setStatus(one.getSpeakState());
			ab.setUpdateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(one.getUpdateTime()));
			ab.setRegisterTime(one.getRegisterTime());
			list.add(ab);
		}
		return list;
	}

	@Override
	public Page<AccountBeanPad> queryAccountInfoList(Pageable pageable) {
		return accountDao.queryAccountInfoList(pageable);
	}

	@Override
	@Transactional
	public void updatePWD(AccountBeanPad accountInfo) {
		accountDao.updatePWD(accountInfo.getPhoneNumber(), accountInfo.getPassword(), accountInfo.getUpdateTime());
	}

	@Override
	@Transactional
	public void resetPwdWeb(AccountBean accountBean) {
		String password = PWDUtil.GetMD5Code("123456");
		SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		try {
			accountDao.updatePWD(accountBean.getPhoneNum(), password, sd.parse(sd.format(new Date())));
		} catch (ParseException e) {
			e.printStackTrace();
		}
	}

	@Override
	public int queryAccountListWebCount(AccountBean accountBean) {
		final String nickName = accountBean.getNickName();
		final String phoneNumber = accountBean.getPhoneNum();
		List<Account> list = new ArrayList<Account>(10);
		Specification<Account> spec = new Specification<Account>() { 
			public Predicate toPredicate(Root<Account> root,  
			        CriteriaQuery<?> query, CriteriaBuilder cb) {  
			    List<Predicate> list = new ArrayList<Predicate>();  
			          
			    if(!StringUtils.isEmpty(nickName) && !StringUtils.isEmpty(phoneNumber)){  
			        list.add(cb.like(root.get("nickName").as(String.class), "%"+ nickName +"%"));  
			        list.add(cb.like(root.get("phoneNumber").as(String.class), "%"+ phoneNumber +"%"));  
			    } else if (!StringUtils.isEmpty(nickName)) {
			        list.add(cb.like(root.get("nickName").as(String.class), "%"+ nickName +"%"));  
			    } else if (!StringUtils.isEmpty(phoneNumber)) {
			        list.add(cb.like(root.get("phoneNumber").as(String.class), "%"+ phoneNumber +"%"));  
			    }
			    Predicate[] p = new Predicate[list.size()];  
			    return cb.and(list.toArray(p));  
			}
		};

		list = accountDao.findAll(spec);
		return list.size();
	}
}
